#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "bytecode_definition.h"
#include "assembly_types.h"
#include "assembly_returns.h"

PBytecode result;

/*prepare definitions*/
#define BYTECODE outtape
#define LABELS labelslist
#define LABELS_QUEUE queuelist
#define STRINGS stringlist
#define PREPARE_FAIL (free(BYTECODE),\
						result = (PBytecode) malloc(sizeof(Bytecode)),\
						result->bytecode = NULL,\
						result->labels = LABELS,\
						result->queue = LABELS_QUEUE,\
						result->strings = STRINGS)
/*/prepare definitions*/

/*returnable errors*/
#define INPUT_ERROR (PREPARE_FAIL,\
						result->bytecodeSize = INPUT_ERROR_A,\
						result)
						
#define NO_MEMORY (PREPARE_FAIL,\
						result->bytecodeSize = NO_FREE_MEMORY_A,\
						result)
						
#define DUPLICATE_LABEL (PREPARE_FAIL,\
						result->bytecodeSize = DUPLICATE_LABEL_A,\
						result)
						
#define NO_SUCH_COMMAND (PREPARE_FAIL,\
						result->bytecodeSize = NO_SUCH_COMMAND_A,\
						result)
						
#define TOO_FAR_LABEL (PREPARE_FAIL,\
						result->bytecodeSize = TOO_FAR_LABEL_A,\
						result)

#define INVALID_FUNC_SIGNATURE (PREPARE_FAIL,\
						result->bytecodeSize = INVALID_FUNC_SIGNATURE_A,\
						result)

#define INVALID_FUNC_ID (PREPARE_FAIL,\
						result->bytecodeSize = INVALID_FUNC_ID_A,\
						result)
/*/returnabe errors*/

#define COMMAND_MAX_LENGTH 10
#define COMMANDS_COUNT 45

/*value types*/
#define FLOAT 1
#define INT 0
/*/value types*/

/*command types*/
#define INSIDE 0	//works with context of current function
#define OUTSIDE 1	//works with context of other function
/*/command types*/

PBytecode assembly(PBytecode intape, char *tapeSlider, unsigned long long int *linecount)
{
	PLabels labelslist = intape->labels, ltmp;
	PLabelsList queuelist = intape->queue, qtmp, qtmp2;
	PStringList stringlist = intape->strings, stmp, stmp2;
	size_t tapesize = intape->bytecodeSize, i, j, t;
	char label[32];
	char command[COMMAND_MAX_LENGTH + 1], *strtmp;
	char factor, valuetype, commandtype;
	unsigned char *outtape = intape->bytecode;
	unsigned short int variable, context;
	unsigned short int callid;
	unsigned short int stringid;
	unsigned long long int polynom;
	long long int integer;
	double fractional, ffactor;
	const char comlist[COMMANDS_COUNT][COMMAND_MAX_LENGTH + 1] = {	
																	"invalid",		//0
																	"load",			//1
																	"dadd",			//2
																	"iadd",			//3
																	"dsub",			//4
																	"isub",			//5
																	"dmul",			//6
																	"imul",			//7
																	"ddiv",			//8
																	"idiv",			//9
																	"imod",			//10
																	"dneg",			//11
																	"ineg",			//12
																	"iprint",		//13
																	"dprint",		//14
																	"sprint",		//15
																	"itod",			//16
																	"dtoi",			//17
																	"stoi",			//18
																	"swap",			//19
																	"pop",			//20
																	"loadiv",		//21
																	"loaddv",		//22
																	"loadsv",		//23
																	"storiv",		//24
																	"stordv",		//25
																	"storsv",		//26
																	"dcmp",			//27
																	"icmp",			//28
																	"jmp",			//29
																	"jne",			//30
																	"je",			//31
																	"jg",			//32
																	"jge",			//33
																	"jl",			//34
																	"jle",			//35
																	"dump",			//36
																	"stop",			//37
																	"call",			//38
																	"callnative",	//39
																	"ret",			//40
																	"break",		//41
																	"iaor",			//42
																	"iaand",		//43
																	"iaxor",		//44
																	};
	while(*tapeSlider != '\0')
		{
		while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
		{
			tapeSlider++;
		}
		if(*tapeSlider == '\n')
		{
			if(linecount != NULL)
			{
				(*linecount)++;
			}
			tapeSlider++;
			continue;
		}
		if(*tapeSlider == '\0')
		{
			break;
		}
		sscanf(tapeSlider, "%10s", command);
		if(command[0] == '@')
		{
			sscanf(tapeSlider, "%31s", label);
			tapeSlider += strlen(label);
			ltmp = labelslist;
			while( (ltmp != NULL) && (!strcmp(label, ltmp->label)) )
			{
				ltmp = ltmp->next;
			}
			if(ltmp == NULL) /*if tmp NULL*/
			{
				ltmp = (PLabels) malloc(sizeof(Labels));
				strcpy(ltmp->label, label);
				ltmp->position = tapesize;
				ltmp->next = labelslist;
				labelslist = ltmp;
			}
			else /*tmp NULL else*/
			{
				return DUPLICATE_LABEL;
			}
			continue;
		}
		else /* @label else*/
		{
			tapeSlider += strlen(command);
			if(command[0] == ';')
			{
				while(*tapeSlider != '\n' && *tapeSlider != '\0')
				{
					tapeSlider++;
				}
				continue;
			}
		}
		i = 0;
		while( (i < COMMANDS_COUNT) && (strcmp(command, comlist[i]) != 0) ) i++;
		switch(i)
		{
			case 0:printf("case 0\n");
					outtape = realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = INVALID;
					break;
			case 1:printf("case 1\n");
					integer = 0;
					fractional = 0;
					ffactor = 0.1;
					factor = 1;
					valuetype = INT;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == '"')
					{
						j = 0;
						tapeSlider++;
						while(tapeSlider[j] != '"')
						{
							if( (*tapeSlider == '\n') && (linecount != NULL) )
							{
								(*linecount)++;
							}
							j++;
						}
						if(j == 0)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = SLOAD0;
							tapeSlider++;
							break;
						}
						strtmp = (char*) malloc(j*sizeof(char));
						strtmp[j] = '\0';
						t = j;
						while(j > 0)
						{
							strtmp[j - 1] = tapeSlider[j - 1];
							j--;
						}
						tapeSlider += t + 1;
						stmp = stringlist;
						stmp2 = stringlist;
						stringid = 1;
						while( (stmp != NULL) && (strcmp(stmp->string,strtmp) != 0) )
						{
							stmp2 = stmp;
							stmp = stmp->next;
							stringid++;
						}
						if(stmp == NULL)
						{
							if(stringlist == NULL)
							{
								stmp = (PStringList) malloc(sizeof(StringList));
								stmp->id = stringid;
								stmp->string = strtmp;
								stmp->next = NULL;
								stringlist = stmp;
							}
							else
							{
								stmp = (PStringList) malloc(sizeof(StringList));
								stmp->id = stringid;
								stmp->string = strtmp;
								stmp->next = NULL;
								stmp2->next = stmp;

							}
							outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
							outtape[tapesize - 3] = SLOAD;
							*( (unsigned short int*) (outtape + tapesize - 2) ) = stringid;
						}
						else
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
							outtape[tapesize - 3] = SLOAD;
							*( (unsigned short int*) (outtape + tapesize - 2) ) = stmp->id;
							free(strtmp);
						}
						break;
					}
					if(*tapeSlider == '-')
					{
						factor = -1;
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						integer = integer*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					if(*tapeSlider == '.')
					{
						valuetype = FLOAT;
						tapeSlider++;
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							fractional = fractional + (*tapeSlider - '0')*ffactor;
							ffactor /= 10.0;
							tapeSlider++;
						}
					}
					if(valuetype == FLOAT)
					{
						fractional += integer;
						fractional *= factor;
						if(fractional == 0.0)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = DLOAD0;
						}
						else if(fractional == 1.0)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = DLOAD1;
						}
						else if(fractional == -1.0)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = DLOADM1;
						}
						else
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 9));
							outtape[tapesize - 9] = DLOAD;
							*( (double*) (outtape + tapesize - 8) ) = fractional;
						}
					}
					else if(valuetype == INT)
					{
						integer *= factor;
						if(integer == 0)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = ILOAD0;
						}
						else if(integer == 1)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = ILOAD1;
						}
						else if(integer == -1)
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
							outtape[tapesize - 1] = ILOADM1;
						}
						else
						{
							outtape = (unsigned char*) realloc(outtape, (tapesize += 9));
							outtape[tapesize - 9] = ILOAD;
							*( (long long int*) (outtape + tapesize - 8) ) = integer;
						}
					}
					break;
			case 2:printf("case 2\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DADD;
					break;
			case 3:printf("case 3\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IADD;
					break;
			case 4:printf("case 4\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DSUB;
					break;
			case 5:printf("case 5\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = ISUB;
					break;
			case 6:printf("case 6\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DMUL;
					break;
			case 7:printf("case 7\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IMUL;
					break;
			case 8:printf("case 8\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DDIV;
					break;
			case 9:printf("case 9\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IDIV;
					break;
			case 10:printf("case 10\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IMOD;
					break;
			case 11:printf("case 11\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DNEG;
					break;
			case 12:printf("case 12\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = INEG;
					break;
			case 13:printf("case 13\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IPRINT;
					break;
			case 14:printf("case 14\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DPRINT;
					break;
			case 15:printf("case 15\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = SPRINT;
					break;
			case 16:printf("case 16\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = I2D;
					break;
			case 17:printf("case 17\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = D2I;
					break;
			case 18:printf("case 18\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = S2I;
					break;
			case 19:printf("case 19\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = SWAP;
					break;
			case 20:printf("case 20\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = POP;
					break;
			case 21:printf("case 21\n");
					commandtype = INSIDE;
					variable = 0;
					context = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						variable = variable*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == ':')
					{
						commandtype = OUTSIDE;
						tapeSlider++;
						while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
						{
							tapeSlider++;
						}
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							context = context*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
					}
					if(commandtype == INSIDE)
					{
						switch(variable)
						{
							case 0:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADIVAR0;
									break;
							case 1:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADIVAR1;
									break;
							case 2:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADIVAR2;
									break;
							case 3:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADIVAR3;
									break;
							default:outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
									outtape[tapesize - 3] = LOADIVAR;
									*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
						}
					}
					else
					{
						outtape = (unsigned char*) realloc(outtape, (tapesize += 5));
						outtape[tapesize - 5] = LOADCTXIVAR;
						*( (unsigned short int*) (outtape + tapesize - 4) ) = context;
						*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
					}
					break;
			case 22:printf("case 22\n");
					commandtype = INSIDE;
					variable = 0;
					context = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						variable = variable*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == ':')
					{
						commandtype = OUTSIDE;
						tapeSlider++;
						while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
						{
							tapeSlider++;
						}
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							context = context*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
					}
					if(commandtype == INSIDE)
					{
						switch(variable)
						{
							case 0:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADDVAR0;
									break;
							case 1:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADDVAR1;
									break;
							case 2:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADDVAR2;
									break;
							case 3:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADDVAR3;
									break;
							default:outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
									outtape[tapesize - 3] = LOADDVAR;
									*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
						}
					}
					else
					{
						outtape = (unsigned char*) realloc(outtape, (tapesize += 5));
						outtape[tapesize - 5] = LOADCTXDVAR;
						*( (unsigned short int*) (outtape + tapesize - 4) ) = context;
						*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
					}
					break;
			case 23:printf("case 23\n");
					commandtype = INSIDE;
					variable = 0;
					context = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						variable = variable*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == ':')
					{
						commandtype = OUTSIDE;
						tapeSlider++;
						while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
						{
							tapeSlider++;
						}
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							context = context*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
					}
					if(commandtype == INSIDE)
					{
						switch(variable)
						{
							case 0:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADSVAR0;
									break;
							case 1:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADSVAR1;
									break;
							case 2:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADSVAR2;
									break;
							case 3:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = LOADSVAR3;
									break;
							default:outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
									outtape[tapesize - 3] = LOADSVAR;
									*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
									break;
						}
					}
					else
					{
						outtape = (unsigned char*) realloc(outtape, (tapesize += 5));
						outtape[tapesize - 5] = LOADCTXSVAR;
						*( (unsigned short int*) (outtape + tapesize - 4) ) = context;
						*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
					}
					break;
			case 24:printf("case 24\n");
					commandtype = INSIDE;
					variable = 0;
					context = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						variable = variable*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == ':')
					{
						commandtype = OUTSIDE;
						tapeSlider++;
						while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
						{
							tapeSlider++;
						}
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							context = context*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
					}
					if(commandtype == INSIDE)
					{
						switch(variable)
						{
							case 0:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREIVAR0;
									break;
							case 1:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREIVAR1;
									break;
							case 2:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREIVAR2;
									break;
							case 3:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREIVAR3;
									break;
							default:outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
									outtape[tapesize - 3] = STOREIVAR;
									*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
									break;
						}
					}
					else
					{
						outtape = (unsigned char*) realloc(outtape, (tapesize += 5));
						outtape[tapesize - 5] = STORECTXIVAR;
						*( (unsigned short int*) (outtape + tapesize - 4) ) = context;
						*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
					}
					break;
			case 25:printf("case 25\n");
					commandtype = INSIDE;
					variable = 0;
					context = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						variable = variable*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == ':')
					{
						commandtype = OUTSIDE;
						tapeSlider++;
						while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
						{
							tapeSlider++;
						}
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							context = context*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
					}
					if(commandtype == INSIDE)
					{
						switch(variable)
						{
							case 0:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREDVAR0;
									break;
							case 1:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREDVAR1;
									break;
							case 2:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREDVAR2;
									break;
							case 3:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STOREDVAR3;
									break;
							default:outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
									outtape[tapesize - 3] = STOREDVAR;
									*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
									break;
						}
					}
					else
					{
						outtape = (unsigned char*) realloc(outtape, (tapesize += 5));
						outtape[tapesize - 5] = STORECTXDVAR;
						*( (unsigned short int*) (outtape + tapesize - 4) ) = context;
						*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
					}
					break;
			case 26:printf("case 26\n");
					commandtype = INSIDE;
					variable = 0;
					context = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						variable = variable*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					if(*tapeSlider == ':')
					{
						commandtype = OUTSIDE;
						tapeSlider++;
						while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
						{
							tapeSlider++;
						}
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							context = context*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
					}
					if(commandtype == INSIDE)
					{
						switch(variable)
						{
							case 0:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STORESVAR0;
									break;
							case 1:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STORESVAR1;
									break;
							case 2:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STORESVAR2;
									break;
							case 3:outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
									outtape[tapesize - 1] = STORESVAR3;
									break;
							default:outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
									outtape[tapesize - 3] = STORESVAR;
									*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
									break;
						}
					}
					else
					{
						outtape = (unsigned char*) realloc(outtape, (tapesize += 5));
						outtape[tapesize - 5] = STORECTXSVAR;
						*( (unsigned short int*) (outtape + tapesize - 4) ) = context;
						*( (unsigned short int*) (outtape + tapesize - 2) ) = variable;
					}
					break;
			case 27:printf("case 27\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DCMP;
					break;
			case 28:printf("case 28\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = ICMP;
					break;
			case 29:printf("case 29\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = JA;
					break;
			case 30:printf("case 30\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = IFICMPNE;
					break;
			case 31:printf("case 31\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = IFICMPE;
					break;
			case 32:printf("case 32\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = IFICMPG;
					break;
			case 33:printf("case 33\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = IFICMPGE;
					break;
			case 34:printf("case 34\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = IFICMPL;
					break;
			case 35:printf("case 35\n");
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					sscanf(tapeSlider, "%31s", label);
					tapeSlider += strlen(label);
					qtmp = (PLabelsList) malloc(sizeof(LabelsList));
					strcpy(qtmp->label, label);
					qtmp->position = tapesize + 1;
					qtmp->line = *linecount;
					qtmp->next = queuelist;
					queuelist = qtmp;
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = IFICMPLE;
					break;
			case 36:printf("case 36\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = DUMP;
					break;
			case 37:printf("case 37\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = STOP;
					break;
			case 38:printf("case 38\n");
					callid = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					polynom = 0;
					if( (*tapeSlider < '0') || (*tapeSlider > '9') )
					{
						j = 0;
						while( (tapeSlider[j] != ' ') && (tapeSlider[j] != '\t') && (tapeSlider[j] != '\n') )
						{
							if( !IS_FUNC_SIGN_CHAR(tapeSlider[j], j) )
							{
								return INVALID_FUNC_SIGNATURE;
							}
							j++;
						}
						for(t = j; t > 0; t--)
						{
							polynom += tapeSlider[t - 1]*POLY_FACTOR;
						}
						callid = (unsigned short int) (polynom%POLY_DEVIDER);
						tapeSlider += j;
					}
					else
					{
						while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
						{
							polynom = polynom*10 + (*tapeSlider - '0');
							tapeSlider++;
						}
						if(polynom > INT16_MAX)
						{
							return INVALID_FUNC_ID;
						}
					}
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = CALL;
					*( (unsigned short int*) (outtape + tapesize - 2) ) = callid;
					break;
			case 39:printf("case 39\n");
					callid = 0;
					while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )
					{
						tapeSlider++;
					}
					while( (*tapeSlider >= '0') && (*tapeSlider <= '9'))
					{
						callid = callid*10 + (*tapeSlider - '0');
						tapeSlider++;
					}
					outtape = (unsigned char*) realloc(outtape, (tapesize += 3));
					outtape[tapesize - 3] = CALLNATIVE;
					*( (unsigned short int*) (outtape + tapesize - 2) ) = callid;
					break;
			case 40:printf("case 40\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = RETURN;
					break;
			case 41:printf("case 41\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = BREAK;
					break;
			case 42:printf("case 42\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IAOR;
					break;
			case 43:printf("case 43\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IAAND;
					break;
			case 44:printf("case 44\n");
					outtape = (unsigned char*) realloc(outtape, (tapesize += 1));
					outtape[tapesize - 1] = IAXOR;
					break;
			default:printf("default\n");
					return NO_SUCH_COMMAND;
		}
		while( (*tapeSlider == ' ') || (*tapeSlider == '\t') )	
		{
			tapeSlider++;
		}
		if(*tapeSlider == ';')
		{
			while( (*tapeSlider != '\n') && (*tapeSlider != '\0') )
			{
				tapeSlider++;
			}
		}
		if( (*tapeSlider != '\n') && (*tapeSlider != '\0') )
		{
			printf("Input error!");
			return INPUT_ERROR;
		}
	}
	qtmp = queuelist;
	qtmp2 = queuelist;
	while(qtmp != NULL)
	{
		ltmp = labelslist;
		while(ltmp != NULL)
		{
			if(strcmp(qtmp->label, ltmp->label) == 0)
			{
				if(ltmp->position > qtmp->position)
				{
					integer = ( (long long int)(ltmp->position - qtmp->position) - 2);
				}
				else
				{
					integer = ( -(long long int)(qtmp->position - ltmp->position) - 2);
				}
				if( (integer < SHRT_MIN) || (integer > SHRT_MAX) )
				{
					if(qtmp != queuelist)
					{
						qtmp2->next = qtmp->next;
						qtmp->next = queuelist;
						queuelist = qtmp;
					}
					printf("too far label\n");
					return TOO_FAR_LABEL;
				}
				*( (signed short int*) (outtape + qtmp->position) ) = (ltmp->position - qtmp->position - 2);
				if(qtmp == queuelist)
				{
					qtmp = qtmp->next;
					free(queuelist);
					queuelist = qtmp;
				}
				else
				{
					qtmp2->next = qtmp->next;
					free(qtmp);
					qtmp = qtmp2->next;
				}
				break;
			}
			ltmp = ltmp->next;
		}
		if(ltmp == NULL)
		{
			qtmp2 = qtmp;
			qtmp = qtmp->next;
		}
	}
	printf("End\t%zu\n", tapesize);
	result = (PBytecode) malloc(sizeof(Bytecode));
	result->bytecode = outtape;
	result->bytecodeSize = tapesize;
	result->labels = labelslist;
	result->queue = queuelist;
	result->strings = stringlist;
	return result;
}

/*
int main()
{
	PBytecode into,out;
	into = (PBytecode) malloc(sizeof(Bytecode));
	into->codesize = 0;
	into->labels = NULL;
	into->queue = NULL;
	into->code = NULL;
	into->strings = NULL;
	out = assemble(into, "load \" \"\n load \"   \" ;y");
	fflush(stdout);
	if(out != NULL){
		printf("%d\t%d\n", out->code[3], *( (unsigned short int*) (out->code + 4)) );
	}
	else
	{
		printf("NULL\n");
	}
	return 0;
}
*/
